package gin

import (
	"fmt"
	"gitee.com/ltotal/ppw_gin/errs"
	"gitee.com/ltotal/ppw_gin/pkg"
	"github.com/SkyAPM/go2sky"
	v3 "github.com/SkyAPM/go2sky-plugins/gin/v3"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
)

const (
	DebugMode   = "debug"
	ReleaseMode = "release"
	TestMode    = "test"
)

type InitInfo struct {
	InitFunc func(interface{}) error
	Params   interface{}
}

type Conf struct {
	RunMode    string
	Routes     []pkg.Routes
	Validators []pkg.Validators
	Recovery   bool
}

func New(ginConf *Conf) *gin.Engine {
	r := gin.Default()

	r.Use(
		tracer(r),
		gcm(),
	)

	if ginConf != nil {
		if ginConf.RunMode != "" {
			gin.SetMode(ginConf.RunMode)
		}

		if ginConf.Recovery {
			r.Use(
				recovery(),
			)
		}

		if ginConf.Routes != nil {
			pkg.API.RegisterRoutes(r, ginConf.Routes...)
		}
		if ginConf.Validators != nil {
			pkg.API.RegisterValidates(ginConf.Validators)
		}
	}

	r.NoRoute(func(c *gin.Context) {
		c.JSON(pkg.API.GetResponse(nil, errs.ErrNotFound))
	})
	return r
}

func gcm() gin.HandlerFunc {
	return func(c *gin.Context) {
		pkg.GCM.SetContext(c)
		c.Next()
	}
}

func tracer(r *gin.Engine) gin.HandlerFunc {
	tracerMidFunc := v3.Middleware(r, go2sky.GetGlobalTracer())
	return func(c *gin.Context) {
		if pkg.Tracer.CheckEnable() {
			tracerMidFunc(c)
		}
	}
}

func recovery() gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			if r := recover(); r != nil {
				resErr := errors.Wrap(errs.ErrCodeUnknown, fmt.Sprintf("Panic recovered: %s\n", r))
				c.AbortWithStatusJSON(pkg.API.GetResponse(nil, resErr))
				return
			}
		}()
		c.Next()
	}
}
